import requests
import base64
import time
import json
import os
import urllib.parse

API_KEY = "dj0IXrWTEE9THqoIjuHdQpcc"
SECRET_KEY = "TjSrT4dNeMQ7QJVPnsPIzM41bpvSgMdf"

# 定义 token 缓存文件路径
TOKEN_CACHE_FILE = os.path.join(os.path.dirname(__file__), 'token_cache.json')

# 全局变量用于缓存 access token 和过期时间
_access_token = None
_token_expire_time = 0

def recognize_text(base64_image_data):
    """
    使用百度 OCR API 识别图片中的文字
    :param base64_image_data: base64编码的图片数据
    :return: 识别结果
    """
    # 获取访问令牌
    access_token = get_access_token()
    if not access_token:
        return {"error": "获取访问令牌失败"}
    
    # 构建 API 请求 URL
    url = f"https://aip.baidubce.com/rest/2.0/ocr/v1/general_basic?access_token={access_token}"
    
    # 图片数据已经是base64编码的，直接使用
    
    # 构建请求参数
    # 对base64图片数据进行URL编码，避免特殊字符导致API解析错误
    url_encoded_image = urllib.parse.quote_plus(base64_image_data)
    payload = f'image={url_encoded_image}&detect_direction=true&detect_language=false&paragraph=false&probability=false'
    
    # 设置请求头
    headers = {
        'Content-Type': 'application/x-www-form-urlencoded',
        'Accept': 'application/json'
    }
    
    # 发送 POST 请求
    # data 参数接收字节流格式的数据，通过 payload.encode("utf-8") 将字符串转换为字节流
    response = requests.request("POST", url, headers=headers, data=payload.encode("utf-8"))
    
    # 设置响应编码并返回结果
    response.encoding = "utf-8"
    return response.json()

def main():
    # 示例使用：请替换为实际的图片路径
    image_path = "example.jpg"
    try:
        # 读取并编码图片文件
        with open(image_path, 'rb') as f:
            base64_image_data = base64.b64encode(f.read()).decode('utf-8')
        
        result = recognize_text(base64_image_data)
        print("OCR 识别结果:", result)
    except Exception as e:
        print(f"识别过程中发生错误: {e}")
    

def _load_token_from_file():
    """
    从文件中加载缓存的 token
    :return: token 和过期时间的元组，如果加载失败返回 (None, 0)
    """
    global _access_token, _token_expire_time
    
    try:
        # 检查文件是否存在
        if os.path.exists(TOKEN_CACHE_FILE):
            with open(TOKEN_CACHE_FILE, 'r', encoding='utf-8') as f:
                data = json.load(f)
                token = data.get('access_token')
                expire_time = data.get('expire_time', 0)
                
                # 验证 token 是否有效
                current_time = time.time()
                if token and expire_time > current_time:
                    _access_token = token
                    _token_expire_time = expire_time
                    return token, expire_time
    except Exception as e:
        print(f"从文件加载 token 失败: {e}")
    
    return None, 0

def _save_token_to_file(token, expire_time):
    """
    将 token 保存到文件中
    :param token: access_token
    :param expire_time: 过期时间
    """
    try:
        # 确保目录存在
        os.makedirs(os.path.dirname(TOKEN_CACHE_FILE), exist_ok=True)
        
        # 保存 token 信息
        data = {
            'access_token': token,
            'expire_time': expire_time,
            'saved_at': time.time()
        }
        
        with open(TOKEN_CACHE_FILE, 'w', encoding='utf-8') as f:
            json.dump(data, f)
    except Exception as e:
        print(f"保存 token 到文件失败: {e}")

def get_access_token():
    """
    使用 AK，SK 生成鉴权签名（Access Token）
    添加文件缓存机制，避免每次都重新请求 token
    :return: access_token，或是None(如果错误)
    """
    global _access_token, _token_expire_time
    current_time = time.time()
    
    # 首先检查内存缓存
    if _access_token and current_time < _token_expire_time:
        return _access_token
    
    # 内存缓存无效，尝试从文件加载
    token, expire_time = _load_token_from_file()
    if token and expire_time > current_time:
        return token
    
    # 没有有效缓存或已过期，重新请求
    url = "https://aip.baidubce.com/oauth/2.0/token"
    params = {"grant_type": "client_credentials", "client_id": API_KEY, "client_secret": SECRET_KEY}
    
    try:
        response = requests.post(url, params=params)
        response.raise_for_status()  # 检查请求是否成功
        result = response.json()
        
        # 更新缓存
        _access_token = result.get("access_token")
        # 百度 access_token 通常有效期为 30 天（2592000秒），但为了安全，我们只缓存 29 天
        expires_in = result.get("expires_in", 2592000)  # 默认 30 天
        # 减去 1 天的时间作为安全边界
        _token_expire_time = current_time + expires_in - 86400
        
        # 保存到文件
        if _access_token:
            _save_token_to_file(_access_token, _token_expire_time)
        
        return _access_token
    except Exception as e:
        print(f"获取 access_token 失败: {e}")
        return None

if __name__ == '__main__':
    main()
